/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package sheep.JUNG.utils;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Shape;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.geom.AffineTransform;
import java.awt.geom.CubicCurve2D;
import java.awt.geom.Point2D;

import edu.uci.ics.jung.graph.Edge;
import edu.uci.ics.jung.visualization.ArrowFactory;
import edu.uci.ics.jung.visualization.PickSupport;
import edu.uci.ics.jung.visualization.SettableVertexLocationFunction;
import edu.uci.ics.jung.visualization.VisualizationViewer;
import edu.uci.ics.jung.visualization.VisualizationViewer.Paintable;
import edu.uci.ics.jung.visualization.control.AbstractGraphMousePlugin;
import sheep.controller.Workspace;
import sheep.model.Task;
import sheep.model.graph.OurVertex;


public class EditingGraphMousePlugin extends AbstractGraphMousePlugin implements
    MouseListener, MouseMotionListener {
    
    SettableVertexLocationFunction vertexLocations;
    OurVertex startVertex;
    Point2D down;
    
    CubicCurve2D rawEdge = new CubicCurve2D.Float();
    Shape edgeShape;
    Shape rawArrowShape;
    Shape arrowShape;
    Paintable edgePaintable;
    Paintable arrowPaintable;
    boolean edgeIsDirected;
    Workspace workSpace;
    
    public EditingGraphMousePlugin(Workspace workSpace) {
        this(MouseEvent.BUTTON1_MASK, workSpace);
        
    }


    public EditingGraphMousePlugin(int modifiers, Workspace workSpace) {
        super(modifiers);
        this.workSpace = workSpace;
        rawEdge.setCurve(0.0f, 0.0f, 0.33f, 100, .66f, -50,
                1.0f, 0.0f);
        rawArrowShape = ArrowFactory.getNotchedArrow(20, 16, 8);
        edgePaintable = new EdgePaintable();
        arrowPaintable = new ArrowPaintable();
    }
    

    public void setVertexLocations(SettableVertexLocationFunction vertexLocations) {
        this.vertexLocations = vertexLocations;
    }
    

    public boolean checkModifiers(MouseEvent e) {
        return (e.getModifiers() & modifiers) != 0;
    }


    public void mousePressed(MouseEvent e) {
        if(checkModifiers(e)) {
            final VisualizationViewer vv =(VisualizationViewer)e.getSource();
            final Point2D p = vv.inverseViewTransform(e.getPoint());
            PickSupport pickSupport = vv.getPickSupport();
            if(pickSupport != null) {
                final OurVertex vertex = (OurVertex)pickSupport.getVertex(p.getX(), p.getY());
                final Edge edge = pickSupport.getEdge(p.getX(), p.getY());
                if(vertex != null) { 
                    startVertex = vertex;
                    down = e.getPoint();
                    transformEdgeShape(down, down);
                    vv.addPostRenderPaintable(edgePaintable);
                    transformArrowShape(down, e.getPoint());
                    vv.addPostRenderPaintable(arrowPaintable);
                    Task task =(Task) vertex.getUserDatum("Key");
                    //this.projet.setSelected(task);
                    //task.setSelected();
                    //EditingGraphMousePlugin.this.pref.getJMainFrame().getCalendarPanel().getJPjojectTabPane().getGraphePanel().update();
                }
                if (edge!=null){
                	//this.projet.setSelectedEdge(edge);
                	//((OurEdge)edge).setSelected(edge);
                }
            }
        }
    }
    

    public void mouseReleased(MouseEvent e) {
        if(checkModifiers(e)) {
            final VisualizationViewer vv = (VisualizationViewer)e.getSource();
            final Point2D p = vv.inverseViewTransform(e.getPoint());
            PickSupport pickSupport = vv.getPickSupport();
            if(pickSupport != null) {
                final OurVertex vertex = (OurVertex)pickSupport.getVertex(p.getX(), p.getY());
                final Edge edge = pickSupport.getEdge(p.getX(), p.getY());
                if(vertex != null && startVertex != null && !((Task)vertex.getUserDatum("Key")).getName()
                		.equals(((Task)startVertex.getUserDatum("Key")).getName()) ){
                    workSpace.getCurrentTask().getGraph().addEdge(startVertex.getTask(),vertex.getTask());
                    //Task task =(Task) vertex.getUserDatum("Key");
                    //this.projet.setSelected(task);
                    //task.setSelected();
                    //EditingGraphMousePlugin.this.pref.getJMainFrame().getCalendarPanel().getJPjojectTabPane().getGraphePanel().update();
                    vv.repaint();
                }
                if (edge!=null){
                	//this.projet.setSelectedEdge(edge);
                	//((OurEdge)edge).setSelected(edge);
                }
            }
            startVertex = null;
            down = null;
            vv.removePostRenderPaintable(edgePaintable);
            vv.removePostRenderPaintable(arrowPaintable);
        }
    }


    public void mouseDragged(MouseEvent e) {
        if(checkModifiers(e)) {
            if(startVertex != null) {
                transformEdgeShape(down, e.getPoint());
                    transformArrowShape(down, e.getPoint());
            }
        }
    }
    

    private void transformEdgeShape(Point2D down, Point2D out) {
        float x1 = (float) down.getX();
        float y1 = (float) down.getY();
        float x2 = (float) out.getX();
        float y2 = (float) out.getY();

        AffineTransform xform = AffineTransform.getTranslateInstance(x1, y1);
        
        float dx = x2-x1;
        float dy = y2-y1;
        float thetaRadians = (float) Math.atan2(dy, dx);
        xform.rotate(thetaRadians);
        float dist = (float) Math.sqrt(dx*dx + dy*dy);
        xform.scale(dist / rawEdge.getBounds().getWidth(), 1.0);
        edgeShape = xform.createTransformedShape(rawEdge);
    }
    
    private void transformArrowShape(Point2D down, Point2D out) {
        float x1 = (float) down.getX();
        float y1 = (float) down.getY();
        float x2 = (float) out.getX();
        float y2 = (float) out.getY();

        AffineTransform xform = AffineTransform.getTranslateInstance(x2, y2);
        
        float dx = x2-x1;
        float dy = y2-y1;
        float thetaRadians = (float) Math.atan2(dy, dx);
        xform.rotate(thetaRadians);
        arrowShape = xform.createTransformedShape(rawArrowShape);
    }
    

    class EdgePaintable implements Paintable {
        
        public void paint(Graphics g) {
            if(edgeShape != null) {
                Color oldColor = g.getColor();
                g.setColor(Color.black);
                ((Graphics2D)g).draw(edgeShape);
                g.setColor(oldColor);
            }
        }
        
        public boolean useTransform() {
            return false;
        }
    }
    

    class ArrowPaintable implements Paintable {
        
        public void paint(Graphics g) {
            if(arrowShape != null) {
                Color oldColor = g.getColor();
                g.setColor(Color.black);
                ((Graphics2D)g).fill(arrowShape);
                g.setColor(oldColor);
            }
        }
        
        public boolean useTransform() {
            return false;
        }
    }
    public void mouseClicked(MouseEvent e) {}
    public void mouseEntered(MouseEvent e) {}
    public void mouseExited(MouseEvent e) {}
    public void mouseMoved(MouseEvent e) {}
}